/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
* View.java
*
* Created on November 26, 2007, 11:30 AM
 */
package gui.genomemap.view;

import gui.genomemap.event.event.WorkerInputEvent;
import gui.genomemap.event.event.WorkerInputListener;
import gui.genomemap.outputModel.OutputModel;
import gui.genomemap.tree.ModelFigTreeNode;
import gui.genomemap.tree.ModelLogTreeNode;
import gui.genomemap.tree.ModelStatTreeNode;
import gui.genomemap.tree.ModelTreeNode;
import gui.genomemap.tree.ViewTree;
import gui.genomemap.tree.ViewTreeNode;
import gui.genomemap.view.inputView.InputView;
import gui.genomemap.view.outputView.OutputView;

import javautil.swing.components.ShortProgressPanel;
import javautil.swing.tabbedPane.MyTabbedPane;

import java.awt.Component;

import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 *
 * @author  stewari1
 */
public class View extends javax.swing.JPanel implements WorkerInputListener {

    /**
     * the worker corresponding to this view.
     */
    private ViewManager manager = null;

    /**
     * progress panel of this view
     */
    private ShortProgressPanel progressPanel = null;

    /**
     * a description of the view
     */
    private String description = null;

    /**
     * input view of this worker view
     */
    private InputView inputView = null;

    /**
     * output view of this worker view
     */
    private OutputView outputView = null;

    /**
     * output model navigator tree of this view
     */
    private ViewTree tree = null;

    /**
     * the type value corresponding to the worker. Must be set in each subclass
     */
    private int type = 0;

    /**
     * Creates new form View
     */
    View() {

        initComponents();


        // set the progress panel and register to the view
        setProgressPanel(new ShortProgressPanel());
        addPropertyChangeListener(getProgressPanel());
    }

    public void displayOutputModel(ModelTreeNode modelNode) {


        // if the node is null show the default output model
        if (modelNode == null) {

            getInputView().setInputModel(null);
            getInputView().setEnabledRunModel(true);
            getOutputView().setOutputModel(null);
            getTabbedPane().setSelectedIndex(
                getTabbedPane().indexOfComponent(getOutputModelPanel()));

            return;
        }

        OutputModel outputModel = modelNode.getOutputModel();

        if (outputModel == null) {
            return;
        }

        if (getTabbedPane().indexOfComponent(getOutputModelPanel()) == -1) {

            getOutputModelPanel().setName("Output Model");
            getTabbedPane().add(getOutputModelPanel());
            getInputView().setInputModel(outputModel.getInputModel());
            getInputView().setEnabledRunModel(outputModel.isEditable());
            getOutputView().setOutputModel(outputModel);
            getTabbedPane().setSelectedIndex(
                getTabbedPane().indexOfComponent(getOutputModelPanel()));
            modelNode.setView(this);

            return;
        }

        getInputView().setInputModel(outputModel.getInputModel());
        getInputView().setEnabledRunModel(outputModel.isEditable());
        getOutputView().setOutputModel(outputModel);
        getTabbedPane().setSelectedIndex(getTabbedPane().indexOfComponent(getOutputModelPanel()));
    }

    public void displayComponent(ModelFigTreeNode modelFigNode) {

        int tabIndex = getCompIndexForNode(modelFigNode);

        if (tabIndex != -1) {

            getTabbedPane().setSelectedIndex(tabIndex);

            return;
        }

        Component comp = modelFigNode.getFigureComp();
        JScrollPane sp = new JScrollPane(comp);

        sp.putClientProperty("node", modelFigNode);
        modelFigNode.setScrollPane(sp);
        getTabbedPane().addTab(comp.getName(), sp);
        getTabbedPane().setSelectedIndex(getTabbedPane().indexOfComponent(sp));
    }

    public void displayText(ViewTreeNode treeNode, boolean html) {

        int tabIndex = getCompIndexForNode(treeNode);

        if (tabIndex != -1) {

            getTabbedPane().setSelectedIndex(tabIndex);

            return;
        }

        String str         = null;
        String tabtitle    = null;
        JScrollPane sp     = new JScrollPane();
        JEditorPane editor = new JEditorPane();

        if (html) {

            editor.setContentType("text/html");

            tabtitle = "Model Statistics";
            str      = ((ModelStatTreeNode) treeNode).getModelStat();

            ((ModelStatTreeNode) treeNode).setEditor(editor);

        } else {

            editor.setContentType("text/plain");

            tabtitle = "Model Log";
            str      = ((ModelLogTreeNode) treeNode).getLog();

            ((ModelLogTreeNode) treeNode).setEditor(editor);
        }

        editor.setText(str);
        sp.setViewportView(editor);
        sp.putClientProperty("node", treeNode);
        getTabbedPane().addTab(tabtitle, sp);
        getTabbedPane().setSelectedIndex(getTabbedPane().indexOfComponent(sp));
    }

    /**
     * finding the component corresponding to the treenode in the tabbed pane
     * @param treeNode
     * @return
     */
    private int getCompIndexForNode(ViewTreeNode treeNode) {

        int compIndex           = -1;
        MyTabbedPane tabbedPane = getTabbedPane();
        int totalTabs           = tabbedPane.getTabCount();

        for (int index = 0; index < totalTabs; index++) {

            JComponent comp   = (JComponent) tabbedPane.getComponentAt(index);
            ViewTreeNode node = (ViewTreeNode) comp.getClientProperty("node");

            if (node == treeNode) {
                return index;
            }    // matching the reference
        }

        return compIndex;
    }

    MyTabbedPane getTabbedPane() {
        return null;
    }

    /**
     * must be overiridden in the subclass to privide a Panel for the output model
     * @return
     */
    JPanel getOutputModelPanel() {
        return null;
    }

    /**
     * must be called in each subclass and the end of setters.
     */
    void addAllListeners() {


        // Note: InputView uses FIFO rule to notify listeners
        // gui management ()enabling or disabling views ..gui related)
        inputView.addWorkerInputListener(this);


        // manager loading the main worker. input-output model options are set by now
        // which will be dispatched to the main worker e.g., an LHood object
        inputView.addWorkerInputListener(manager);


        // manager posting global messages on the view` which in turn gets posted on the view`s
        // progress panel
        manager.addPropertyChangeListener(getProgressPanel());
    }

    public String getDescription() {
        return description;
    }

    void setDescription(String description) {
        this.description = description;
    }

    public ViewManager getManager() {
        return manager;
    }

    void setManager(ViewManager manager) {
        this.manager = manager;
    }

    public InputView getInputView() {
        return inputView;
    }

    void setInputView(InputView inputView) {

        this.inputView = inputView;

        getInputView().setView(this);
    }

    public OutputView getOutputView() {
        return outputView;
    }

    void setOutputView(OutputView workerOutputView) {

        this.outputView = workerOutputView;

        getOutputView().setView(this);
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */


    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);

        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(
                0, 400, Short.MAX_VALUE));
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(
                0, 300, Short.MAX_VALUE));

    }    // </editor-fold>//GEN-END:initComponents


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    /**
     * Getter for property tree.
     * @return Value of property tree.
     */
    public ViewTree getTree() {
        return this.tree;
    }

    /**
     * Setter for property tree.
     * @param tree New value of property tree.
     */
    void setTree(ViewTree tree) {

        this.tree = tree;


        // this will update the input and output view when a node is double clicked
        tree.setView(this);
    }

    public ShortProgressPanel getProgressPanel() {
        return progressPanel;
    }

    void setProgressPanel(ShortProgressPanel progressPanel) {
        this.progressPanel = progressPanel;
    }

    @Override
    public void doComGLHoodInput(WorkerInputEvent e) {}

    @Override
    public void doComPLHoodInput(WorkerInputEvent e) {}

    @Override
    public void doComJLHoodInput(WorkerInputEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void doAnnealInput(WorkerInputEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void doProgCurveInput(WorkerInputEvent e) {}

    public int getType() {
        return type;
    }

    void setType(int type) {
        this.type = type;
    }
}
